///////// content-rotator/index.php

<?php
/*------------------------------------------------------------------------------
Plugin Name: Content Rotator
Plugin URI: http://www.tipsfor.us/
Description: Sample plugin for rotating chunks of custom content. 
post on your WordPress site. 
Author: Everett Griffiths
Version: 0.1
Author URI: http://www.tipsfor.us/
------------------------------------------------------------------------------*/ 

// include() or require() any necessary files here...
// include widget class
include_once('includes/ContentRotatorWidget.php');
// include helper functions
include_once('includes/ContentRotator.php');

// Tie into WordPress Hooks and any functions that should run on load.
// register widget
add_action('widgets_init', 'ContentRotatorWidget::register_this_widget');
// add sub-menu item in plugins menu in admin
add_action('admin_menu', 'ContentRotator::add_menu_item');
?>

///////// content-rotator/includes/ContentRotatorWidget.php

<?php
/**
* ContentRotatorWidget extends WP_Widget
*
* This implements a WordPress widget designed to randomize chunks of content.
*/   
class ContentRotatorWidget extends WP_Widget
   {
      public $name = 'Content Rotator';
	  public $description = 'Rotates chunks of content on a periodic basis';
      /* List all controllable options here along with a default value.
      The values can be distinct for each instance of the widget. */
      public $control_options = array(
		   'title'               => 'Content Rotator',
		   'seconds_shelf_life'   => 86400,   // 86400 seconds in a day
		);
		
		
      //!!! Magic Functions   
      // The constructor. 
      function __construct()
      {
         $widget_options = array(
            'classname'    => __CLASS__,
            'description'    => $this->widget_desc,
         );
         parent::__construct( __CLASS__, $this->name, $widget_options, $this->control_options);
      }
	  
	  /**
		* Displays the widget form in the manager, used for editing its settings
		*
		* @param   array    $instance   The settings for the particular instance of the widget
		* @return none   No value is returned directly, but form elements are printed. 
		*/
		public function form($instance)
		{
		   $placeholders = array();
		   foreach ($this->control_options as $key => $val)
		   {
			  $placeholders[ $key .'.id' ]    = $this->get_field_id($key);
			  $placeholders[ $key .'.name' ]    = $this->get_field_name( $key );
			  // This helps us avoid "Undefined index" notices.
			  if ( isset($instance[ $key ] ) )
			  {
				 $placeholders[ $key .'.value' ]   = esc_attr( $instance[$key ] );
				 
			  }
			  // Use the default (for new instances)
			  else 
			  {
				 $placeholders[ $key .'.value' ]   = $this->control_options[ $key ];
			  }
		   }
		   
		   $tpl = file_get_contents( dirname(dirname(__FILE__)) .'/tpls/widget_controls.tpl');
		   print ContentRotator::parse($tpl, $placeholders);
		}
	  
      //!!! Static Functions
      static function register_this_widget()
      {
         register_widget(__CLASS__);
      }
	  
	  /**
	   * Displays content to the front-end, using the tpls/widget.tpl template.
	   *
	   * @param array   $args    Display arguments
	   * @param array    $instance   The settings for the particular instance of the widget
	   * @return none  No direct output. This should instead print 	output directly.
	   */
	   public function widget($args, $instance)
		{      

		   if (!isset($instance['manufacture_date']) || time() >= ($instance['manufacture_date'] + $instance['seconds_shelf_life'] ) )  {
			  $instance['content'] = ContentRotator::get_random_content($instance);
			  $instance['manufacture_date'] = time();
			  $all_instances = $this->get_settings();
			 
			  $all_instances[ $this->number ] = $instance;
			  $this->save_settings($all_instances);
		   }
		   $placeholders = array_merge($args, $instance);
		   $tpl = file_get_contents( dirname(dirname(__FILE__)) .'/tpls/widget.tpl');
		   print ContentRotator::parse($tpl, $placeholders);   
		}
   }
 ?>
 
 ///////// content-rotator/includes/ContentRotator.php
 
 <?php
/**
* ContentRotator
*
* Helper functions that assist the ContentRotatorWidget class
*/
class ContentRotator {
	/**
	* Adds a menu item inside the WordPress admin
	*/
	static function add_menu_item()
	{
	   add_submenu_page(
		  'plugins.php',                   		// Menu page to attach to
		  'Content Rotator Configuration',    	// page title
		  'Content Rotator',                	// menu title
		  'manage_options',                		// permissions
		  'content-rotation',               	// page-name (used in the URL)
		  'ContentRotator::generate_admin_page' // clicking callback function
	   );
	}
	/**
	* Controller that generates admin page
	*/
	static function generate_admin_page()
	{
	   	$msg = ''; // used to display a success message on updates
	   	if (!empty($_POST) && check_admin_referer('content_rotation_admin_options_update','content_rotation_admin_nonce'))
		{
			// store variables in database
			update_option('content_rotation_content_separator',  stripslashes($_POST['separator']) );
			update_option('content_rotation_content_block', stripslashes($_POST['content_block']) );   
			$msg = '<div class="updated"><p>Your settings have been <strong>updated</strong></p></div>';
		}
		include('admin_page.php');
	}
		
	
	/**
	Fetch and return a piece of random content
	*/
	static function get_random_content(){   
		// get data from database
	   $separator       = get_option('content_rotation_content_separator');
	   $content_block    = get_option('content_rotation_content_block');
	  
	
		// Ensure that the user has entered valid settings
		if ( empty($content_block) )
		{
			return '';
		}
		elseif (empty($separator))
		{
			return $content_block;
		}
	   // Get an array of non-empty chunks
	   $content_array = explode($separator, $content_block);
	   $sanitized_array = array();
	   foreach ($content_array as $chunk)
	   {
		  $chunk = trim($chunk);
		  if (!empty($chunk))
		  {
			 $sanitized_array[] = $chunk;
		  }
	   }
	   $chunk_cnt = count($sanitized_array);
	   if ( $chunk_cnt)
	   {
		  $n = rand(0, ($chunk_cnt - 1));
		  return $sanitized_array[$n];
	   }
	   else
	   {
		  return '';
	   }
	}
	
	/**
   * parse
   *
   * A simple parsing function for basic templating.
   *
   * @param $tpl   string    A formatting string containing [+placeholders+]
   * @param $hash   array   An associative array containing keys and values e.g. array('key' => 'value');
   * @return   string      Placeholders corresponding to the keys of the hash will be replaced with the values the 	
   							resulting string will be returned.
   */
	static function parse($tpl, $hash) {
		foreach ($hash as $key => $value) {
			$tpl = str_replace('[+'.$key.'+]', $value, $tpl);
		}
		return $tpl;
	}
}
/*EOF*/
?>

 ///////// content-rotator/includes/admin_page.php
 
 <div class="wrap">
      <?php screen_icon(); ?>
      <h2>Content Rotator Administration</h2>
      <?php print $msg; ?>
      <form action="" method="post" id="content_rotation_admin_options_form">
         <h3><label for="separator">Separator</label></h3>
         <p>This separates units of content. It can be simple like a comma, or complex like &lt;!--SEPARATOR--&gt;<br/>
			<input type="text" id="separator" name="separator" value="<?php print esc_attr( get_option('content_rotation_content_separator') ); ?>" /></p>
         <h3><label for="content_block">Content Block</label></h3>
         <p>
            Use the separator above to separate blocks of content, e.g. <code>man, bear, pig</code><br/>
            or <code>&lt;a href="http://mysite.com/"&gt;MySite.com&lt;/a&gt;&lt;--SEPARATOR--&gt;
            &lt;a href="http://yoursite.com/"&gt;YourSite.com&lt;/
a&gt;</code><br/>
            <textarea rows="5" cols="50" id="content_block" name="content_block"><?php print get_option('content_rotation_content_block'); ?></textarea>
         </p>
         <p class="submit"><input type="submit" name="submit" value="Update" /></p>
        <?php 
			// for security
			wp_nonce_field('content_rotation_admin_options_update','content_rotation_admin_nonce'); 
		?>
      </form>   
   </div>
   
 ///////// content-rotator/tpls/widget_controls.tpl
 
 <!-- 
This .tpl file is used when editing a widget's options in the WP manager.
It should only contain form *elements*; WordPress will supply the opening and closing <form> tags.
For each key in the ContentRotatorWidget::$control_options array, you will have the following placeholders available:
   [+your_key.id+]      - used inside id attributes, e.g. id="[+your_key.id+]"
   [+your_key.name+]   - used inside name attributes, e.g.name="[+your_key.name+]"
   [+your_key.value+]   - contains the current value of the option WordPress appends text to the names and id's to allow for multiple instances of the widget, so don't try hard-coding values here.   
-->
	<label for="[+title.id+]">Title</label><br />
   	<input id="[+title.id+]" name="[+title.name+]" value="[+title.value+]" /><br />
    <label for="[+seconds_shelf_life.id+]">Shelf Life (in seconds)</label><br />
	<input id="[+seconds_shelf_life.id+]" name="[+seconds_shelf_life.name+]" value="[+seconds_shelf_life.value+]" />
	
 ///////// content-rotator/tpls/widget.tpl
 
 [+before_widget+]
   [+before_title+]
      [+title+]
   [+after_title+]
   [+content+]
[+after_widget+]